package com.gpstracker.services;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;
import android.webkit.WebView.FindListener;

import com.gpstracker.db.MyDatabase;

public class GpsReceiverService extends Service implements LocationListener {

	private final int ONE_SECOND = 1000;
	private final int MIN_DISTANCE = 50;
	private final float ACCURACY_THRESHOLD = 50;

	private Runner runner;
	private volatile boolean keepRunning;
	private LocationManager locationManager = null;
	private volatile Location blackboard = null;

	private final String TAG = "GPS_RECEIVER_SERVICE";
	MyDatabase db;
	private int seconds_range;
	private int seconds_range_network;
	char c;
	private SharedPreferences prefs;



	class Runner extends Thread{

		@Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			workerLoop();
		}

	}


//	@Override
//	public int onStartCommand(Intent intent, int flags, int startId) {
//		// TODO Auto-generated method stub
//		int i = super.onStartCommand(intent, flags, startId);
//		c = intent.getCharExtra("com.gpstracker.PROVIDER_TYPE", 'N');
//
//		switch (c) {
//		case 'G':
//			startGpsProvider();
//			Log.i(TAG, "GPS");
//			break;
//		case 'N':
//			startNetworkProvider();
//			Log.i(TAG, "NETWORK");
//			break;
//		case 'B':
//			startBothProvider();
//			Log.i(TAG, "BEST");
//			break;
//		default:
//			Log.i(TAG, "default");
//
//			break;
//		}
//
//		return i;
//	}


	@Override
	public void onCreate() {

		Log.i(TAG, "oncreate");
		keepRunning = true;
		runner = new Runner();
		runner.start();
		db=new MyDatabase(getApplicationContext());
		db.open();

		prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
		seconds_range = Integer.parseInt(prefs.getString("timeRange", "300"))*ONE_SECOND;
		seconds_range_network = (seconds_range/3)*2 ;
		
		startBothProvider();

	}

	@Override
	public void onDestroy() {
		keepRunning = false;
		Log.i(TAG, "onDestroy");
		synchronized(this) {
			this.notify();
		}
	}



	private void workerLoop() { 


		// Main worker loop for the service
		while (keepRunning) {
			Log.i(TAG, "THREAD KEEPRUNNING");
			while(this.blackboard == null && keepRunning)
				synchronized(this) {
					try {
						Log.i(TAG, "WAIT");
						wait();
					} catch(InterruptedException e) {


						throw new RuntimeException(e);
					}
				}
			if(keepRunning){
				Log.i(TAG, "WORKING AGAIN");
				final Location locationUpdate = this.blackboard;
				String loc= "LON: "+locationUpdate.getLongitude() + "LAT: "+ locationUpdate.getLatitude();
				Log.i("LOC_CHANGED", loc);
				String mode= prefs.getString("mode", "");

				String provider = locationUpdate.getProvider();
				if(provider.equals("network")){
					if(locationUpdate.getAccuracy()<=ACCURACY_THRESHOLD)
						db.insertLocation(locationUpdate.getLongitude(), locationUpdate.getLatitude(), locationUpdate.getProvider(), locationUpdate.getAccuracy(), locationUpdate.getSpeed(), mode);
				}
				else
					db.insertLocation(locationUpdate.getLongitude(), locationUpdate.getLatitude(), locationUpdate.getProvider(), locationUpdate.getAccuracy(), locationUpdate.getSpeed(), mode);
				Log.i("LOCATION_NUM_ROWS", Integer.toString(db.fetchLocations().getCount()));
				this.blackboard = null;
			}

		}   
		Log.i(TAG, "Stopping workerLoop");
		stopLocationManager();
	}


//	private void startGpsProvider() {
//		if (locationManager == null)
//			locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
//
//		Criteria criteria = new Criteria();
//		criteria.setAccuracy(Criteria.ACCURACY_LOW);
//		criteria.setAltitudeRequired(false);
//		criteria.setBearingRequired(false);
//		criteria.setCostAllowed(false);
//		criteria.setSpeedRequired(false);
//		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, seconds_range, MIN_DISTANCE, (LocationListener) this);
//
//
//	}

	private void startBothProvider(){
		if (locationManager == null)
			locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, seconds_range, MIN_DISTANCE, (LocationListener) this);
		locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, seconds_range_network, MIN_DISTANCE, (LocationListener) this);

	}


//	private void startNetworkProvider() {
//		if (locationManager == null)
//			locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
//		locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, seconds_range_network, MIN_DISTANCE, (LocationListener) this);
//
//	}

	private void stopLocationManager() {
		if (locationManager != null)
			locationManager.removeUpdates((LocationListener) this);
		locationManager = null;
	}

	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void onLocationChanged(Location location) {
		// TODO Auto-generated method stub
		if( location != null ){
			synchronized(this) {
				this.blackboard = location;
				this.notify();
			}
			Log.i(TAG, "ON_LOCATION_CHANGED: " + location.getProvider());
		}
	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onProviderDisabled(String provider) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onProviderEnabled(String provider) {
		// TODO Auto-generated method stub
		Log.i(TAG, "PROVIDER_ENABLED: " + provider);

	}

}

